/*
 * Copyright (c) 2009, Jan Pastor. All Rights Reserved.
 */

package sk.jp.commons.ui;

import java.util.Map;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.ListModel;

/**
 * {@link JList} or {@link JComboBox} item that contains item identifier (key)
 * and item value presented to user.
 * <p>Value can be string label, or any subclass of
 * {@link JComponent}, renderable by e.g. {@link ListOptionCellRenderer}. <br>
 * Usage:<br>
 * <pre>list.setRenderer(new ListOptionCellRenderer());</pre>
 * @param <K>
 * @param <V>
 */
public class ListOption<K, V> {

    private final K itemKey;
    private final V itemValue;

    //----------------------------------------------------------------------

    public ListOption(K itemKey, V itemValue) {
        if(itemKey == null) throw new NullPointerException("Parameter itemKey is null");
        if(itemValue == null) throw new NullPointerException("Parameter itemValue is null");
        
        this.itemKey = itemKey;
        this.itemValue = itemValue;
    }

    //----------------------------------------------------------------------

    public K getItemKey() {
        return itemKey;
    }

    public V getItemValue() {
        return itemValue;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("ListOption");
        sb.append("{itemKey=").append(itemKey);
        sb.append(", itemValue=").append(itemValue);
        sb.append('}');
        return sb.toString();
    }

    /**
     * Builds list model that contains {@link ListOption} from given map,
     * where map.key is used as key in list option, and value as option value.
     * @param map list item map to transform.
     * @param <K> option key class.
     * @param <V> option value class.
     * @return a list model instance that contains {@link ListOption}s.
     */
    public static <K,V> ComboBoxModel mapToListOptionModel(Map<K,V> map){
        DefaultComboBoxModel listModel = new DefaultComboBoxModel();
        for (Map.Entry<K, V> entry : map.entrySet()) {
            listModel.addElement(new ListOption<K,V>(entry.getKey(), entry.getValue()));
        }
        return listModel;
    }

    /**
     * Search for {@link ListOption} item in given list model, that has specified
     * key.
     * @param listModel
     * @param key
     * @return list option or null if no option was found.
     * @throws ClassCastException if given <code>listModel</c> doesn't contains
     * instances of {@link ListOption}.
     */
    public static ListOption getOption(ListModel listModel, Object key){
        int size = listModel.getSize();
        for(int i = 0; i < size; i++){
            Object element = listModel.getElementAt(i);
            ListOption option = (ListOption) element;
            if(option.getItemKey().equals(key)){
                return option;
            }
        }
        return null;
    }

}
